package com.zkthink.ceres.promotion.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.zkthink.base.request.PageParams;
import com.zkthink.base.service.SuperServiceImpl;
import com.zkthink.ceres.common.enums.YesOrNoEnum;
import com.zkthink.ceres.common.event.OrderCancelEvent;
import com.zkthink.ceres.common.event.OrderFinishEvent;
import com.zkthink.ceres.common.event.OrderPaidEvent;
import com.zkthink.ceres.order.dto.event.OrderEventDTO;
import com.zkthink.ceres.promotion.dao.*;
import com.zkthink.ceres.promotion.dto.SalesOrderPageDTO;
import com.zkthink.ceres.promotion.entity.*;
import com.zkthink.ceres.promotion.enums.SalesAuditStatusEnum;
import com.zkthink.ceres.promotion.enums.SalesCommissionTypeEnum;
import com.zkthink.ceres.promotion.enums.SalesOrderSettleStatusEnum;
import com.zkthink.ceres.promotion.service.SalesOrderService;
import com.zkthink.ceres.promotion.vo.admin.SalesOrderPageVO;
import com.zkthink.context.BaseContextHandler;
import com.zkthink.database.mybatis.conditions.Wraps;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.List;

/**
 * <p>
 * 分销订单
 * </p>
 *
 * @author kellen
 * @date 2020-08-22
 */
@Slf4j
@Service
@AllArgsConstructor
public class SalesOrderServiceImpl extends SuperServiceImpl<SalesOrderMapper, SalesOrder> implements
    SalesOrderService {

  private SalesCustomerMapper salesCustomerMapper;

  private SalesMapper salesMapper;

  private SalesLevelMapper salesLevelMapper;

  private SalesRelationConfigMapper salesRelationConfigMapper;

  /**
   * 分页查询分销订单
   */
  @Override
  public IPage<SalesOrderPageVO> page(PageParams<SalesOrderPageDTO> params) {
    SalesOrderPageDTO pageDTO = params.getModel();
    pageDTO.setTenantCode(BaseContextHandler.getTenant());
    return this.baseMapper.page(params.getPage(), pageDTO);
  }

  @EventListener
  @Async
  public void handleOrderPaid(OrderPaidEvent orderPaidEvent){
    if (orderPaidEvent != null) {
      if (orderPaidEvent.getParentId() == 0) {
        List<OrderEventDTO> adminOrderDTOList = orderPaidEvent.getChildOrderDTOList();
        for (OrderEventDTO orderEventDTO : adminOrderDTOList) {
          distributeInner(orderEventDTO.getTenantCode(),orderPaidEvent.getMid(),orderEventDTO.getOrderSum(),orderEventDTO.getOrderCode());
        }
      } else {
        distributeInner(orderPaidEvent.getTenantCode(),orderPaidEvent.getMid(),orderPaidEvent.getOrderSum(),orderPaidEvent.getOrderCode());
      }
    }
  }

  @EventListener
  @Async
  public void handleOrderFinish(OrderFinishEvent orderFinishEvent){
    if (orderFinishEvent != null) {
      SalesOrder salesOrder = new SalesOrder();
      salesOrder.setSettleStatus(YesOrNoEnum.YES.getCode());
      baseMapper.update(salesOrder, Wraps.<SalesOrder>lbQ().eq(SalesOrder::getOrderNo,orderFinishEvent.getOrderCode())
              .eq(SalesOrder::getIsDelete,YesOrNoEnum.NO.getCode()));

      List<SalesOrder> salesOrderList = baseMapper.selectList(Wraps.<SalesOrder>lbQ().eq(SalesOrder::getOrderNo,orderFinishEvent.getOrderCode())
              .eq(SalesOrder::getIsDelete,YesOrNoEnum.NO.getCode()));
      for(SalesOrder sOrder:salesOrderList){
        if(sOrder.getProfitSid() != null && sOrder.getProfitSid() != 0){
          handleLevelUp(sOrder.getProfitSid());
        }
      }
    }
  }

  @EventListener
  @Async
  public void handleOrderCancel(OrderCancelEvent orderCancelEvent){
    if (orderCancelEvent != null) {
      SalesOrder salesOrder = new SalesOrder();
      salesOrder.setIsDelete(YesOrNoEnum.YES.getCode());
      baseMapper.update(salesOrder, Wraps.<SalesOrder>lbQ().eq(SalesOrder::getOrderNo,orderCancelEvent.getOrderCode())
              .eq(SalesOrder::getIsDelete,YesOrNoEnum.NO.getCode()));
    }
  }

  /**
   * 针对具体子订单进行分销
   */
  private void distributeInner(String tenantCode, Long mid, Long orderSum, String orderCode){
    //针对子订单对应的商户查询分销绑定关系
    SalesCustomer salesCustomer = salesCustomerMapper.selectOne(Wraps.<SalesCustomer>lbQ().eq(SalesCustomer::getTenantCode, tenantCode)
            .eq(SalesCustomer::getMid, mid)
            .eq(SalesCustomer::getIsValid, 1)
            .eq(SalesCustomer::getIsDelete, 0));
    if (salesCustomer != null) {
      Sales sales = salesMapper.selectById(salesCustomer.getSid());
      //该销售员必须是合法的，并且审核通过的 并且没有被删除的
      if (validSales(sales)) {
        SalesLevel salesLevel = salesLevelMapper.selectById(sales.getLevelId());
        BigDecimal directRate = salesLevel.getDirectRate();
        BigDecimal indirectRate = salesLevel.getIndirectRate();

        //分销给直接分销员
        distribute(sales.getId(),sales.getId(), tenantCode,mid,orderSum,orderCode,directRate);

        //查询分销员是否还有上级，如果有分佣给上级
        if(sales.getPid() != null){
          Sales salesUpper = salesMapper.selectById(sales.getPid());
          if(validSales(salesUpper)){
            distribute(sales.getId(),sales.getPid(),tenantCode,mid,orderSum,orderCode,indirectRate);
          }
        }
      }
    }
  }

  /**
   * 校验分销员是否合法
   * @param sales
   * @return
   */
  private boolean validSales(Sales sales){
    if (sales != null && sales.getIsDelete() != YesOrNoEnum.YES.getCode()
            && sales.getIsValid() == YesOrNoEnum.YES.getCode()
            && sales.getAuditStatus() == SalesAuditStatusEnum.PASS.getCode()) {
      return true;
    }
    return false;
  }

  /**
   * 分销的具体操作
   * @param salesId
   * @param profitSalesId
   * @param tenantCode
   * @param mid
   * @param orderSum
   * @param orderCode
   * @param rate
   */
  private void distribute(Long salesId, Long profitSalesId, String tenantCode, Long mid, Long orderSum, String orderCode, BigDecimal rate){
      System.out.println(rate.divide(new BigDecimal(100)));
      BigDecimal commissionUpper = new BigDecimal(orderSum).multiply(rate.divide(new BigDecimal(100)));
      SalesOrder salesOrder = SalesOrder.builder().mid(mid)
              .commission(commissionUpper.longValue())
              .orderAmount(orderSum)
              .orderNo(orderCode)
              .settleStatus(YesOrNoEnum.NO.getCode())
              .sid(salesId)
              .profitSid(profitSalesId)
              .tenantCode(tenantCode)
              .type(salesId.equals(profitSalesId) ? SalesCommissionTypeEnum.DIRECT.getCode() : SalesCommissionTypeEnum.IN_DIRECT.getCode())
              .isDelete(0)
              .build();
      baseMapper.insert(salesOrder);
  }

  /**
   * 处理升级问题
   */
  private void handleLevelUp(Long salesId){
    Sales sales = salesMapper.selectById(salesId);
    if(sales != null && sales.getIsValid() == YesOrNoEnum.YES.getCode()
        && sales.getAuditStatus() == SalesAuditStatusEnum.PASS.getCode()
        && sales.getIsDelete() == YesOrNoEnum.NO.getCode()){
      SalesLevel salesLevel = salesLevelMapper.selectById(sales.getLevelId());
      Integer sort = salesLevel.getSort();
      if(sort == null){
        sort = 1;
      }
      //查询当前分销员分销数据
      Long commissionSum = baseMapper.selectCommissionSumByProfitSidAndTenantCode(sales.getId(), sales.getTenantCode(),
              SalesOrderSettleStatusEnum.SETTLED.getCode(), SalesCommissionTypeEnum.DIRECT.getCode());

      //下级分销员数量
      Integer subordinateCount = salesMapper.selectCount(Wraps.<Sales>lbQ().eq(Sales::getPid,sales.getId())
              .eq(Sales::getIsValid,YesOrNoEnum.YES.getCode())
              .eq(Sales::getAuditStatus,SalesAuditStatusEnum.PASS.getCode())
              .eq(Sales::getIsDelete,YesOrNoEnum.NO.getCode()));

      //绑定的客户数量
      Integer customerCount = salesCustomerMapper.selectCount(Wraps.<SalesCustomer>lbQ().eq(SalesCustomer::getSid, sales.getId())
              .eq(SalesCustomer::getIsValid,YesOrNoEnum.YES.getCode())
              .eq(SalesCustomer::getIsDelete,YesOrNoEnum.NO.getCode()));

      //查询出比当前等级更高的等级，按照顺序倒序排，这种情况下，如果规则允许，分销员可能直接从1级升到3级，即跨级升级
      List<SalesLevel> salesLevelList = salesLevelMapper.selectList(Wraps.<SalesLevel>lbQ().eq(SalesLevel::getTenantCode,sales.getTenantCode())
              .gt(SalesLevel::getSort,sort)
              .eq(SalesLevel::getIsDelete,YesOrNoEnum.NO.getCode())
              .orderByDesc(SalesLevel::getSort));
      for(SalesLevel sLevel:salesLevelList){
        if(sLevel.getRule() != null){
          Long ruleCommissionSum = sLevel.getRule().getRuleTotalAmountLimit();
          Long ruleSubordinateCount = sLevel.getRule().getInviteCustomerLimit();
          Long ruleCustomerCount = sLevel.getRule().getInviteCustomerLimit();

          if(ruleCommissionSum != null && commissionSum >= ruleCommissionSum
                  && ruleSubordinateCount != null && subordinateCount >= ruleSubordinateCount
                  && ruleCustomerCount != null && customerCount >= ruleCustomerCount){
            //符合当前等级的要求，升级
            sales.setLevelId(sLevel.getId());
            salesMapper.updateById(sales);

            //升级之后，跳出循环
            break;
          }
        }
      }
    }
  }
}
